/*
    作者：zx
    时间：2022.11.24
    描述：互斥锁
*/

#include "cpu/irq.h"
#include "ipc/mutex.h"

void mutex_init(mutex_t * mutex)
{
    mutex->locked_count = 0;
    list_init(&mutex->wait_list);
    mutex->owner = 0; 
}

void mutex_lock(mutex_t * mutex)
{
    irq_status_t irq_status = irq_enter_protection();
    task_t * curr_task = curr_task_get();
    if(mutex->locked_count == 0)
    {
        mutex->owner = curr_task;
        mutex->locked_count++;
    }
    else if (mutex->owner == curr_task)
    {
        mutex->locked_count++;
    }
    else
    {
        task_remove_ready(curr_task);
        list_insert_last(&mutex->wait_list, &curr_task->wait_node);
        task_manager_update();
    }
    irq_quit_protection(irq_status);
}

void mutex_unlock(mutex_t * mutex)
{
    irq_status_t irq_status = irq_enter_protection();
    task_t * curr_task = curr_task_get();
    
    // 锁拥有者才能释放锁 
    if (mutex->owner == curr_task)
    {
        if(--mutex->locked_count==0)
        {
            mutex->owner = 0;
            if(list_count(&mutex->wait_list)>0)
            {
                list_node_t * task_wait_node = list_remove_first(&mutex->wait_list);
                task_t * task = list_node_parent(task_wait_node, task_t, wait_node);
                task_set_to_ready(task);

                mutex->locked_count = 1;
                mutex->owner = task;
            }
        }   
    }
    irq_quit_protection(irq_status);
}